/*
 * test_machine.cpp
 *
 *  Created on: May 19, 2014
 *      Author: killerg
 */

#include "share/net_c.h"
#include <vector>
#include "share/util.h"
#include "share/clock.h"

using namespace std;

enum EStatus {
	Noexist = -1,
	Initing = 0,
	Running = 1,
	Shutting = 2,
};

static const char* NAME[] = {
		"Noexist", "Initing", "Running", "Shutting",
};

struct proc_t {
	string name;
	EStatus status;
	bool keep;
	int pid;
	string refresh;
	string cmd;
};

static map<string, proc_t> proces;
static string machine_name = "uc1";
bool test_machine() {

	my_clock_t clock;
	tran_c tran;

	clock.init(1);
	tran.init();

	while (true) {
		clock.begin_update();
		if (!tran.is_connected() && !tran.is_connecting()) {
			tran.connect("127.0.0.1:9876", false, [&tran]() {
				tran.write_line(fmt_cstr("%s", machine_name.c_str()));
			});
		}
		char buffer[1024];
		int len = tran.read_line(buffer);
		if (len > 0) {
			vector<string> args;
			split(buffer, " ", args);
			if (args.size() > 0) {
				if (args[0] == "i") {
					for (int i=1; i<args.size(); ++i) {
						if (proces.count(args[i]) > 0) {
							printf("%s exists\n", args[i].c_str());
							continue;
						}

						proc_t proc;
						proc.keep = false;
						proc.name = args[i];
						proc.status = Noexist;
						proc.pid = -1;
						proc.refresh = "";
						proc.cmd = fmt_cstr("%s %s", "curver/bin/server", proc.name.c_str());
						proces[proc.name] = proc;

					}
				} else if (args[0] == "u") {
					for (int i=1; i<args.size(); ++i) {
						if (proces.count(args[i]) == 0) {
							printf("%s noexists\n", args[i].c_str());
							continue;
						}

						proces.erase(args[i]);
					}
				} else if (args[0] == "b") {
					for (int i=1; i<args.size(); ++i) {
						auto &name = args[i];
						if (proces.count(name) == 0) {
							printf("%s noexists\n", args[i].c_str());
							continue;
						}
						auto &proc = proces[name];
						if (proc.status != Noexist) {
							printf("%s noinvalid\n", args[i].c_str());
							continue;
						}

						execute(fmt_cstr("%s -b", proc.cmd.c_str()));
					}
				} else if (args[0] == "s") {
					for (int i=1; i<args.size(); ++i) {
						auto &name = args[i];
						if (proces.count(name) == 0) {
							printf("%s noexists\n", args[i].c_str());
							continue;
						}
						auto &proc = proces[name];
						if (proc.status != Initing && proc.status != Running) {
							printf("%s no run\n", args[i].c_str());
							continue;
						}

						execute(fmt_cstr("%s -s", proc.cmd.c_str()));
					}
				} else if (args[0] == "q") {
					for (int i=1; i<args.size(); ++i) {
						auto &name = args[i];
						if (proces.count(name) == 0) {
							printf("%s noexists\n", args[i].c_str());
							continue;
						}
						auto &proc = proces[name];
						if (proc.status != Initing && proc.status != Running) {
							printf("%s no run\n", args[i].c_str());
							continue;
						}

						tran.write_line(fmt_cstr("query %s %s", machine_name.c_str(), proc.name.c_str(), NAME[proc.status+1]));
					}
				} else if (args[0] == "k") {
					for (int i=1; i<args.size(); ++i) {
						auto &name = args[i];
						if (proces.count(name) == 0) {
							printf("%s noexists\n", args[i].c_str());
							continue;
						}
						proces[name].keep = !proces[name].keep;
					}
				}
			}

			//tran.write_line(fmt_cstr("%s commit", machine_name.c_str()));
		}
		tran.update();
		clock.end_update();

		if (clock.sec_jump) {
			for (auto &itr : proces) {
				string result = execute(fmt_cstr("%s -q", itr.second.cmd.c_str()));
				if (result.empty()) {
					itr.second.status = Noexist;
				} else {
					char status[64];
					int pid = 0;
					int shut = 1;
					char refresh[128];

					if (4 != sscanf(result.c_str(), "%s %d %d %s", &status, &pid, &shut, &refresh))
						continue;

					itr.second.pid = pid;
					itr.second.refresh = refresh;
					for (int i=0; i<Shutting+1; ++i) {
						if (strcmp(status, NAME[i]) == 0)
							itr.second.status = EStatus(i-1);
					}
				}

				if (itr.second.keep && itr.second.status == Noexist) {
					execute(fmt_cstr("%s -b", itr.second.cmd.c_str()));
				}
			}
		}

		clock.wait_frame();
	}

	tran.destroy();
	clock.destroy();

	return true;
}
